﻿using MCPlatform.Communicate.Modbus;
using MCPlatform.Communicate.Modbus.Modbus;
using MCPlatform.Models.Motions;
using MCPlatform.UI.Components;
using MCPlatform.UI.Controls.Models;
using Newtonsoft.Json.Linq;
using Panuon.WPF.UI;
using System;
using System.CodeDom;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Security.RightsManagement;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Input;

namespace MCPlatform.Builder.WorkStation.Robot
{
    public class RobotBase : ViewModelBase
    {
        #region Fields

        #region Write
        private readonly ushort _controlAddr = 552;

        private readonly ushort _initialAddr = 8203;

        private readonly ushort _resetAddr = 384;

        private readonly ushort _setVelRateAddr = 535;

       // private readonly ushort _toPlaceAddr = 8196;

        private readonly ushort _toPickAndPlaceAddr = 8194;

        private readonly ushort _toPlaceNGAddr = 8195;

        private readonly ushort _pickTrayColumnNumberAddr = 8197;

        //private readonly ushort  _pickTrayRowNumberAddr = 8198;

        //private readonly ushort _pickTrayLevelNumberAddr = 8199;

        //private readonly ushort _placeTrayColumnNumberAddr = 8200;

        //private readonly ushort _placeTrayRowNumberAddr = 8201;

        //private readonly ushort _placeTrayLevelNumberAddr = 8202;


        private readonly ushort _pickTrayIDAddr = 8205;

        private readonly ushort _placeTrayIDAddr = 8206;

        private readonly ushort _shapeDoneAddr = 8207;

        private readonly ushort _photoDoneAddr = 8208;

        private readonly ushort _shapeStartAddr = 8209;

        private readonly ushort _shapeClampAddr = 8210;

        private readonly ushort _shapeRobotClampAddr = 8227;


        private readonly ushort _photoAngleAddr = 8224;

        private readonly ushort _photoStartAddr = 8211;

        private readonly ushort _photoResultAddr = 8212;

        private readonly ushort _shapeResultAddr = 8213;


        private readonly ushort _toWaitPosAddr = 8230;

        private readonly ushort _enableAddr = 6;


        private readonly ushort _AxisPosAddr = 240;

        #endregion


        #region Read

        private readonly ushort _initialDoneAddr = 8192;

        private readonly ushort _RobotMoveDoneAddr = 8193;

        private readonly ushort _RobotStatus = 553;

        #endregion

        protected ManualResetEvent pauseEvent = new ManualResetEvent(true);

        public event Func<Task<bool>>? ShapeStartEvent;

        public event Func<Task<bool>>? ShapeDoneEvent;

        public event Func<Task<bool>>? PhotoStartEvent;

        #endregion


        #region Properties

        public string ControlName { get; set; }

        public TCPMaster? TCPMaster { get; set; }

        public RobotPositionModel RobotPositionModel { get; set; }


        #endregion

        #region CTOR

        public RobotBase(TCPMaster? tcp)
        {
            TCPMaster = tcp;
            if (TCPMaster !=null && !TCPMaster.Connected)
            {
                TCPMaster.Connection().GetAwaiter();
            }

        }

        public RobotBase()
        {
            TCPMaster = null;
        }

        #endregion

        #region Robot Control Methods
        /// <summary>
        /// 机器人控制
        /// </summary>
        /// <param name="value">1：open;2:Release Run;3:Stop;4:Pause;6:ReleaseAndRun;11:Step Into;12:Step Over;13:Step Out</param>
        /// <returns></returns>
        public async Task<bool> RobotControlAsync(ushort value)
        {
            if (TCPMaster is null)
            {
                return false;
            }

            //机器人运行
            await TCPMaster.WriteSingleRegisterAsync(_controlAddr, value);

            return true;


        }

        public async Task<bool> IsRobotReady()
        {
           var res = await ReadRobotStatus();
            if (res == 0 || res == 32 || res == 2 || res == 20 || res == 41)
            {
                if (res == 41)
                {
                    await ResumnAsync();
                }
                return false;
            }

            return true;
        }
        public async Task<bool> InitialAsync(int timeOut = 10000)
        {
            if (TCPMaster is null)
            {
                return false;
            }

            //如果未连接，先连接
            if (!TCPMaster.Connected)
            {
                await TCPMaster.Connection();

                await Task.Delay(2000);
            }

            if (!TCPMaster.Connected) { Toast.Show("机器人未连接成功！", targetWindow: ToastWindow.MainWindow); return false; }

            //查看机器人是否报错，报错则复位
            if (!await IsRobotReady())
            {
                await ResetAsync();
                await Task.Delay(2000);
            }
            await StopAsync();

            await Task.Delay(1000);

            //机器人打开并运行
            await RobotControlAsync(6);

            //设置速度比例30%
            await SetRobotVelRate(30);

            bool result = false;

            //让机器人回原
            await TCPMaster.WriteSingleRegisterAsync(_initialAddr, 0);
            await Task.Delay(500);
            await TCPMaster.WriteSingleRegisterAsync(_initialAddr, 1);

            await Task.Run(async () =>
            {

                Stopwatch stopwatch = Stopwatch.StartNew();
                while (stopwatch.ElapsedMilliseconds < timeOut)
                {
                    var res = await TCPMaster.ReadHoldingRegistersAsync(_initialDoneAddr, 1);

                    if (res == null)
                    {
                        break;
                    }
                    else if (res[0] == 1)
                    {
                        result = true;
                        break;
                    }
                }
            });
            //关闭回原信号
            await TCPMaster.WriteSingleRegisterAsync(_initialAddr, 0);
            return result;
        }

        public async Task<bool> RobotToWaitAsync(int timeOut = 10000)
        {
            if (TCPMaster is null)
            {
                return false;
            }

            //如果未连接，先连接
            if (!TCPMaster.Connected)
            {
                await TCPMaster.Connection();

                await Task.Delay(2000);
            }

            if (!TCPMaster.Connected) { Toast.Show("机器人未连接成功！", targetWindow: ToastWindow.MainWindow); return false; }

            
           

            bool result = false;

            //让机器人回原
            await TCPMaster.WriteSingleRegisterAsync(_toWaitPosAddr, 0);
            await Task.Delay(100);
            await TCPMaster.WriteSingleRegisterAsync(_toWaitPosAddr, 1);

            await Task.Run(async () =>
            {

                Stopwatch stopwatch = Stopwatch.StartNew();
                while (stopwatch.ElapsedMilliseconds < timeOut)
                {
                    var res = await TCPMaster.ReadHoldingRegistersAsync(_RobotMoveDoneAddr, 1);

                    if (res == null)
                    {
                        break;
                    }
                    else if (res[0] == 1)
                    {
                        result = true;
                        break;
                    }
                }
            });
            //关闭回原信号
            await TCPMaster.WriteSingleRegisterAsync(_toWaitPosAddr, 0);
            return result;
        }

        public async Task<bool> PickAndPlaceAsync(ushort[] trayInfo, ushort pickTrayID, ushort placeTrayID,CancellationToken cancellationToken,bool isPickAndPlaceNG = false,  int timeOut = 20000)
        {

            if (TCPMaster is null)
            {
                return false;
            }
            try
            {
                bool result = false;
                await TCPMaster.WriteSingleRegisterAsync(_toPickAndPlaceAddr, 0);
                await TCPMaster.WriteSingleRegisterAsync(_pickTrayIDAddr, pickTrayID);
                await TCPMaster.WriteSingleRegisterAsync(_placeTrayIDAddr, placeTrayID);
                await TCPMaster.WriteMultipleRegistersAsync(_pickTrayColumnNumberAddr, trayInfo);

                if (isPickAndPlaceNG)
                {
                    await TCPMaster.WriteSingleRegisterAsync(_toPlaceNGAddr, 1);
                }
                else
                {
                    await TCPMaster.WriteSingleRegisterAsync(_toPickAndPlaceAddr, 1);
                }
              

                await Task.Run(async () =>
                {
                    try
                    {
                        Stopwatch stopwatch = Stopwatch.StartNew();
                        bool isStopwatchRunning = true;

                        while ((stopwatch.ElapsedMilliseconds < timeOut) && !cancellationToken.IsCancellationRequested)
                        {

                            if (pauseEvent.WaitOne())
                            {
                                if (isStopwatchRunning)
                                {
                                    stopwatch.Stop();
                                    isStopwatchRunning = false;
                                }
                            }
                            else
                            {
                                if (!isStopwatchRunning)
                                {
                                    stopwatch.Start();
                                    isStopwatchRunning = true;
                                }
                            }



                            var res = await TCPMaster.ReadHoldingRegistersAsync(_RobotMoveDoneAddr, 1);

                            if (res == null)
                            {
                                break;
                            }
                            else if (res[0] == 1)
                            {
                                result = true;
                                break;
                            }

                          


                        }

                      
                       
                    }
                    catch (OperationCanceledException)
                    {
                        throw;
                    }
                    catch (Exception)
                    {

                        throw;
                    }
                  

                });


                await TCPMaster.WriteSingleRegisterAsync(_toPlaceNGAddr, 0);
                await TCPMaster.WriteSingleRegisterAsync(_toPickAndPlaceAddr, 0);

                return result;

            }
            catch (Exception)
            {

                throw;
            }
           
        }


        public async Task<bool> LoadPickAndPlaceAsync(ushort[] trayInfo, ushort pickTrayID, ushort placeTrayID, CancellationToken cancellationToken, int timeOut = 20000)
        {

            if (TCPMaster is null)
            {
                return false;
            }
            try
            {
                bool result = true;
                await TCPMaster.WriteSingleRegisterAsync(_photoDoneAddr, 0);
                await TCPMaster.WriteSingleRegisterAsync(_shapeResultAddr, 0);
                await TCPMaster.WriteSingleRegisterAsync(_toPickAndPlaceAddr, 0);
                await TCPMaster.WriteSingleRegisterAsync(_shapeDoneAddr, 0);
                await TCPMaster.WriteSingleRegisterAsync(_photoResultAddr, 0);
                await TCPMaster.WriteSingleRegisterAsync(_pickTrayIDAddr, pickTrayID);
                await TCPMaster.WriteSingleRegisterAsync(_placeTrayIDAddr, placeTrayID);
                await TCPMaster.WriteMultipleRegistersAsync(_pickTrayColumnNumberAddr, trayInfo);
                await TCPMaster.WriteSingleRegisterAsync(_toPickAndPlaceAddr, 1);
               

                await Task.Run(async () =>
                {
                    try
                    {
                        Stopwatch stopwatch = Stopwatch.StartNew();
                        bool isStopwatchRunning = true;
                        bool isShapeRunning = true;
                        bool isShapeDone = false;
                        bool isPhotoDone = true;
                        bool photoRes = false;

                        while ((stopwatch.ElapsedMilliseconds < timeOut) && !cancellationToken.IsCancellationRequested)
                        {

                            if (pauseEvent.WaitOne())
                            {
                                if (isStopwatchRunning)
                                {
                                    stopwatch.Stop();
                                    isStopwatchRunning = false;
                                }
                            }
                            else
                            {
                                if (!isStopwatchRunning)
                                {
                                    stopwatch.Start();
                                    isStopwatchRunning = true;
                                }
                            }

                            //开始拍照
                            var photoStart = await TCPMaster.ReadHoldingRegistersAsync(_photoStartAddr, 1);
                            if (photoStart?[0] == 1 && isPhotoDone)
                            {
                                isPhotoDone = false;
                                 photoRes = await PhotoStartEvent!.Invoke();
                                //拍照失败 返回
                                if (!photoRes)
                                {
                                    result = false;
                                    //return;
                                }


                            }

                            if (photoRes)
                            {
                                //整型开始
                                var shapeStart = await TCPMaster.ReadHoldingRegistersAsync(_shapeStartAddr, 1);
                                if (shapeStart?[0] == 1 && isShapeRunning)
                                {
                                    isShapeRunning = false;

                                    bool shapeResult = await ShapeStartEvent!.Invoke();
                                    //bool shapeResult = true;

                                    //整型完成
                                    await TCPMaster.WriteSingleRegisterAsync(_shapeDoneAddr, 1);

                                    if (shapeResult)
                                    {
                                       //整形成功
                                        await TCPMaster.WriteSingleRegisterAsync(_shapeResultAddr, 1);
                                    }
                                    else
                                    {
                                        //整形失败
                                        await TCPMaster.WriteSingleRegisterAsync(_shapeResultAddr, 2);
                                        result = false;
                                    }
                                }
                                //整形完成回调
                                if (shapeStart?[0] == 0 && !isShapeRunning && !isShapeDone)
                                {
                                    isShapeDone = true;

                                    await ShapeDoneEvent!.Invoke();

                                }
                            }

                          

                            //取放料完成
                            var res = await TCPMaster.ReadHoldingRegistersAsync(_RobotMoveDoneAddr, 1);

                            if (res?[0] == 1)
                            {
                               
                                break;
                            }
                           




                        }



                    }
                    catch (OperationCanceledException)
                    {
                        throw;
                    }
                    catch (Exception)
                    {

                        throw;
                    }


                });


                await TCPMaster.WriteSingleRegisterAsync(_toPickAndPlaceAddr, 0);
                return result;

            }
            catch (Exception)
            {

                throw;
            }

        }

        public async Task RobotRotateAngle(string angle)
        {
            ; if (TCPMaster is null)
            {
                return;
            }
            //写1 是OK，2是NG，3是OK 但角度负数
            ushort photoResult = 1;

            double.TryParse(angle, out double ang);

            if (ang<0)
            {
                ang = ang * -1;
                photoResult = 3;
            }
            double temp = ang * 1000;
            long angSend = (long)(temp);

            

            await TCPMaster.WriteSingleRegisterAsync(_photoResultAddr, photoResult);

            await TCPMaster.WriteSingleRegisterByLongAsync(_photoAngleAddr, angSend);
            //await Task.Delay(1000);


            await TCPMaster.WriteSingleRegisterAsync(_photoDoneAddr, 1);

        }


        public async Task WriteDataToRobot(ushort addr = 0,ushort value = 1)
        {
            ; if (TCPMaster is null)
            {
                return;
            }

            if (addr == 0)
            {
                addr = _shapeClampAddr;
            }
           
            await TCPMaster.WriteSingleRegisterAsync(addr, value);       
        }

        public async Task<bool> ReadDataByRobot(ushort addr = 0, ushort value = 1,double timeOut = 5)
        {
            ; if (TCPMaster is null)
            {
                return false;
            }

            if (addr == 0)
            {
                addr = _shapeClampAddr;
            }

            bool res = false;

            await Task.Run(async () =>
            {
                Stopwatch stopwatch = Stopwatch.StartNew();
                while (stopwatch.Elapsed.TotalSeconds < timeOut) 
                {
                   var result =  await TCPMaster.ReadHoldingRegistersAsync(_shapeRobotClampAddr, 1);

                    if ( result?[0] == 1)
                    {
                        res = true;
                        break;
                    }
                    
                }
            });

            return res;

           
        }

        public async Task RobotToNG()
        {
            ; if (TCPMaster is null)
            {
                return;
            }

            //写2是NG
            await TCPMaster.WriteSingleRegisterAsync(_photoResultAddr, 2);
            await TCPMaster.WriteSingleRegisterAsync(_photoDoneAddr, 1);
          


        }
        public async Task SetRobotVelRate(double velRate)
        {
            if (TCPMaster is null)
            {
                return;
            }
            await TCPMaster.WriteSingleRegisterAsync(_setVelRateAddr, (ushort)velRate);
        }

        public async Task ResetAsync()
        {
            if (TCPMaster is null)
            {
                return;
            }
            await TCPMaster.WriteSingleRegisterAsync(_resetAddr, 1);
        }

        public async Task StopAsync()
        {
            if (TCPMaster is null)
            {
                return;
            }
            pauseEvent.Set();
            //机器人停止
            await RobotControlAsync(3);
        }

        public async Task PauseAsync()
        {
            if (TCPMaster is null)
            {
                return;
            }
            //机器人暂停
            pauseEvent.Reset();
            await RobotControlAsync(4);
        }

        public async Task ResumnAsync()
        {
            if (TCPMaster is null)
            {
                return;
            }
            //释放运行
            pauseEvent.Set();
            await RobotControlAsync(2);
        }


        /// <summary>
        /// 使能
        /// </summary>
        /// <param name="enable"></param>
        /// <returns></returns>
        public async Task Enable()
        {
            if (TCPMaster is null)
            {
                return;
            }
            float[] enables = new float[4] { 1, 1, 1, 1 };
            await TCPMaster.WriteMultipleRegistersAsync(_enableAddr, enables);
        }


        /// <summary>
        /// 失能
        /// </summary>
        /// <returns></returns>
        public async Task Disable()
        {
            if (TCPMaster is null)
            {
                return;
            }
            float[] enables = new float[4];
            await TCPMaster.WriteMultipleRegistersAsync(_enableAddr, enables);
        }

        /// <summary>
        /// 读取机器人各轴的当前位置
        /// </summary>
        /// <returns>XYZABC坐标位置数组</returns>
        public async Task<long[]?> ReadRobotAxisPos()
        {
            if (TCPMaster is null)
            {
                return null;
            }
          
            return await TCPMaster.ReadHoldingRegistersWithLongAsync(_AxisPosAddr, 12);
        }


        /// <summary>
        /// 机器人状态
        /// </summary>
        /// <returns>
        /// 0:Busy;1:Checking;2:Failed;10:Cannot open;11:Opening;12:Opened;20:Cannot run;21:Running;30:cannot stop;31:Stopping;32:Stopped;
        /// 40:Cannot pause;41:Pause;50:Cannot Step;51:Stepped;
        /// </returns>
        public async Task<ushort> ReadRobotStatus()
        {

            if (TCPMaster is null)
            {
                return 0;
            }
            var res = await TCPMaster.ReadHoldingRegistersAsync(_RobotStatus, 1);
            if (res is null)
            {
                return 0;
            }
            return res[0];
        }


        #endregion

        #region Tray info Methods

        /// <summary>
        /// 获取测试Tray的行列信息
        /// </summary>
        /// <param name="testTrayModel">Tray对象</param>
        /// <param name="checkType">获取类型：0：空料，1：OK料，2：NG料</param>
        /// <param name="defaultTrayID">默认的Tray ID，ID在机器人中定义，作为取料的料盘，则是1，作为放料料盘则是2</param>
        /// <param name="anotherTrayId">Tray ID另一个是4</param>
        /// <returns>bool:获取的结果，行号，列号，Tray盘ID</returns>
        public static (bool, ushort, ushort, ushort) GetTestTrayInfo(TestTrayModel testTrayModel, int checkType, ushort defaultTrayID, ushort anotherTrayId = 4)
        {
            //遍历字典，获取行里面的有料的值
            foreach (var rows in testTrayModel.RowItemsMap.Values)
            {
                foreach (var item in rows)
                {
                    if (item.Value == checkType)
                    {
                        //key 是行
                        ushort key = (ushort)testTrayModel.RowItemsMap.FirstOrDefault(kvp => kvp.Value == rows).Key;
                        ushort column = (ushort)(rows.IndexOf(item) + 1);

                        //偶数取料料盘ID 是4，奇数则是1
                        ushort id = ((key % 2) == 0 ? anotherTrayId : defaultTrayID);


                        return (true, key, column, id);
                    }
                }
            }

            return (false, 0, 0, defaultTrayID);


        }


        public static (bool, ushort, ushort, ushort) GetTestTrayInfoByLoad(TestTrayModel testTrayModel, int checkType, ushort defaultTrayID, ushort anotherTrayId = 4)
        {
            //遍历字典，获取行里面的有料的值
            foreach (var rows in testTrayModel.RowItemsMap.Values)
            {
                foreach (var item in rows)
                {
                    if (item.Value == checkType)
                    {
                        //key 是行
                        ushort key = (ushort)testTrayModel.RowItemsMap.FirstOrDefault(kvp => kvp.Value == rows).Key;
                        ushort column = (ushort)(rows.IndexOf(item) + 1);

                        //偶数取料料盘ID 是4，奇数则是1
                        ushort id = ((key % 2) == 0 ? anotherTrayId : defaultTrayID);

                        if (key == 1 || key == 7)
                        {
                            id = 5;
                        }


                        return (true, key, column, id);
                    }
                }
            }

            return (false, 0, 0, defaultTrayID);


        }

        public static (bool, ushort, ushort, ushort,bool) GetTestTrayInfoForUnload(TestTrayModel testTrayModel, ushort defaultTrayID, ushort anotherTrayId = 4)
        {
            //遍历字典，获取行里面的有料的值
            foreach (var rows in testTrayModel.RowItemsMap.Values)
            {
                foreach (var item in rows)
                {
                   

                    if (item.Value == 1)
                    {
                        //key 是行
                        ushort key = (ushort)testTrayModel.RowItemsMap.FirstOrDefault(kvp => kvp.Value == rows).Key;
                        ushort column = (ushort)(rows.IndexOf(item) + 1);

                        //偶数取料料盘ID 是4，奇数则是1
                        ushort id = ((key % 2) == 0 ? anotherTrayId : defaultTrayID);

                        if (key == 1 || key == 7)
                        {
                            id = 5;
                        }

                        return (true, key, column, id,true);
                    }
                    else if (item.Value == 2)
                    {
                        //key 是行
                        ushort key = (ushort)testTrayModel.RowItemsMap.FirstOrDefault(kvp => kvp.Value == rows).Key;
                        ushort column = (ushort)(rows.IndexOf(item) + 1);

                        //偶数取料料盘ID 是4，奇数则是1
                        ushort id = ((key % 2) == 0 ? anotherTrayId : defaultTrayID);

                        if (key == 1 || key == 7)
                        {
                            id = 5;
                        }

                        return (true, key, column, id, false);
                    }
                }
            }

            return (false, 0, 0, defaultTrayID,false);


        }

        /// <summary>
        /// 查看测试Tray的行数是否是第一行和最后一行，因为第一行和最后一行只有第三和第四列，所以要把行列信息转换后发给机器人
        /// </summary>
        /// <param name="rowNumber">行号</param>
        /// <param name="columnNumber">列号</param>
        /// <param name="newRowNumber">新行号</param>
        /// <param name="newColumnNumver">新列号</param>
        public static void CheckRowIsFirtOrLast(ushort rowNumber, ushort columnNumber, out ushort newRowNumber, out ushort newColumnNumver)
        {
            newRowNumber = rowNumber;

            if ((rowNumber % 2) == 0)
            {
                newRowNumber = (ushort)(rowNumber / 2);
            }
            else
            {
                if (rowNumber == 3)
                {
                    newRowNumber = 2;
                }
                else if (rowNumber == 5)
                {
                    newRowNumber = 3;
                }
                else if (rowNumber == 7)
                {
                    newRowNumber = 4;
                }

            }

            if (rowNumber == 1 || rowNumber == 7)
            {
                if (columnNumber == 1)
                {
                    newColumnNumver = 3;
                    return;
                }
                else if (columnNumber == 2)
                {
                    newColumnNumver = 4;
                    return;
                }
            }

            newColumnNumver = columnNumber;
        }


        public static void CheckRowIsFirtOrLastByLoad(ushort rowNumber, ushort columnNumber, out ushort newRowNumber, out ushort newColumnNumver)
        {
            newRowNumber = rowNumber;

            if ((rowNumber % 2) == 0)
            {
                newRowNumber = (ushort)(rowNumber / 2);
            }
            else
            {
                //第三行变放料第一行 料盘id 2 
                if (rowNumber == 3)
                {
                    newRowNumber = 1;
                }
                //第5行变放料第二行 料盘id 2
                else if (rowNumber == 5)
                {
                    newRowNumber = 2;
                }
                //第七行变放料第二行，料盘id 5
                else if (rowNumber == 7)
                {
                    newRowNumber = 2;
                }

            }

            //第一行 第七行

            //if (rowNumber == 1 || rowNumber == 7)
            //{
            //    if (columnNumber == 1)
            //    {
            //        newColumnNumver = 3;
            //        return;
            //    }
            //    else if (columnNumber == 2)
            //    {
            //        newColumnNumver = 4;
            //        return;
            //    }
            //}

            newColumnNumver = columnNumber;
        }

        /// <summary>
        /// 设置测试Tray的信息
        /// </summary>
        /// <param name="testTrayModel">测试Tray对象</param>
        /// <param name="rowNmber">行号</param>
        /// <param name="columnNumber">列号</param>
        /// <param name="setValue">设置的值，0：空，1：OK料，2：NG料</param>
        public static void SetTestTrayInfo(TestTrayModel testTrayModel, ushort rowNmber, ushort columnNumber, int setValue)
        {

            testTrayModel.RowItemsMap[rowNmber][columnNumber - 1].Value = setValue;
        }

      
        /// <summary>
        /// 获取上下料Tray的信息
        /// </summary>
        /// <param name="tray">Tray对象</param>
        /// <param name="checkType">检查类型，0：空，1：OK，2：NG</param>
        /// <param name="columnCount">列的数量，默认是9</param>
        /// <returns>bool：获取结果，行号，列号</returns>
        public static (bool, ushort, ushort) GetTrayInfo(ObservableCollection<TrayModel> tray, int checkType, ushort columnCount = 9)
        {
            foreach (var trayModel in tray)
            {
                if (trayModel.Value == checkType)
                {
                    ushort index = (ushort)tray.IndexOf(trayModel);

                    ushort row = (ushort)((index / columnCount) + 1);

                    ushort column = (ushort)((index % columnCount) + 1);


                    return (true, row, column);
                }
            }


            return (false, 0, 0);
        }

        /// <summary>
        /// 设置上下料盘信号
        /// </summary>
        /// <param name="tray">tray对象</param>
        /// <param name="row">行号</param>
        /// <param name="column">列号</param>
        /// <param name="setValue">设置值</param>
        /// <param name="columnCount">列数量，默认=9</param>
        public static void SetTrayInfo(ObservableCollection<TrayModel> tray, ushort row, ushort column, int setValue, ushort columnCount = 9)
        {
            var index = (row - 1) * columnCount + column - 1;
            tray[index].Value = setValue;
        }


        public static void UpdateTestTrayInfo(TestTrayModel testTrayModel, int setValue)
        {
            foreach (var rows in testTrayModel.RowItemsMap.Values)
            {
                foreach (var item in rows)
                {
                    item.Value = setValue;
                }
            }
        }


        public static void UpdateTestTrayInfo(TestTrayModel sourceTestTrayModel, TestTrayModel destinationTestTrayModel)
        {
           
            //先找出目标的字典，再从字典里面找到行，再找到行中的索引，给索引赋值
            foreach (var rows in destinationTestTrayModel.RowItemsMap)
            {
                var key = rows.Key;
                var value = rows.Value;
                foreach (var item in value)
                {
                    int index = value.IndexOf(item);
                    item.Value = sourceTestTrayModel.RowItemsMap[key][index].Value;
                }
            }

        }

        public static void UpdateTrayInfo(ObservableCollection<TrayModel> trayModel,int setValue)
        {
            foreach (var model in trayModel)
            {
                model.Value = setValue;
            }
        }
        #endregion


    }
}
